using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using BalloonCS;

namespace VirtualScreenMaximizer
{

    

    public partial class Form1 : Form
    {



        Maximizer.ConfiguredKey maxKey;
        Maximizer.ConfiguredKey resKey;
        //List<MockScreen> confScreens = null;
        ConfiguredMockScreens configuredMockScreens = null;


        System.Configuration.Configuration config = null;
        public Form1()
        {
            InitializeComponent();
            loadSettings();
        }
        private void loadSettings()
        {
            config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (config.AppSettings.Settings["maximize"] != null)
            {
                string maxS = config.AppSettings.Settings["maximize"].Value;
                if (maxS != null)
                {
                    string[] maxP = maxS.Split(new char[1] { ' ' }, 2);

                    if (maxP.Length > 0)
                    {
                        if (maxP[0].Length >= 5)
                        {
                            maxKey = new Maximizer.ConfiguredKey(maxP[0][0] == '1', maxP[0][1] == '1', maxP[0][2] == '1', Convert.ToInt32(maxP[0].Substring(3)));
                        }
                        if (maxP.Length > 1)
                        {
                            textBoxMaxHK.Text = maxP[1];
                        }
                    }
                }

            }

            if (config.AppSettings.Settings["restore"] != null)
            {
                string resS = config.AppSettings.Settings["restore"].Value;
                if (resS != null)
                {
                    string[] resP = resS.Split(new char[1] { ' ' }, 2);

                    if (resP.Length > 0)
                    {
                        if (resP[0].Length >= 5)
                        {
                            resKey = new Maximizer.ConfiguredKey(resP[0][0] == '1', resP[0][1] == '1', resP[0][2] == '1', Convert.ToInt32(resP[0].Substring(3)));
                        }
                        if (resP.Length > 1)
                        {
                            textBoxResHK.Text = resP[1];
                        }
                    }
                }
            }

            configuredMockScreens = new ConfiguredMockScreens();
            if (config.AppSettings.Settings["NumberOfConfiguredScreens"] != null)
            {
                string nrS = config.AppSettings.Settings["NumberOfConfiguredScreens"].Value;
                //config.AppSettings.Settings.Add("ScreenDeviceName" + i, ms.DeviceName);
                //config.AppSettings.Settings.Add("ScreenVertical" + i, ms.Vertical?"true":"false");
                //config.AppSettings.Settings.Add("ScreenHorizontal" + i, ms.Horizontal ? "true" : "false");
                if (nrS != null)
                {
                    int nrSc = Convert.ToInt32(nrS);
                    for (int i = 0; i < nrSc; i++)
                    {
                        //config.AppSettings.Settings ["ScreenDeviceName" + i].Value;
                        MockScreen ms = new MockScreen(config.AppSettings.Settings["ScreenDeviceName" + i].Value);
                        ms.Vertical = (config.AppSettings.Settings["ScreenVertical" + i].Value.ToLower() == "true");
                        ms.Horizontal = (config.AppSettings.Settings["ScreenHorizontal" + i].Value.ToLower() == "true");
                        configuredMockScreens.Add(ms.DeviceName.ToString(), ms);
                        Console.WriteLine(ms.Horizontal);
                    }
                }
            }


            if (config.AppSettings.Settings["UseWorkingArea"] != null)
            {
                bool useWA = false;

                Boolean.TryParse(config.AppSettings.Settings["UseWorkingArea"].Value, out useWA);

                configuredMockScreens.UseWorkingArea = useWA;
                UseWorkingAreaCheckbox.Checked = configuredMockScreens.UseWorkingArea;
            }

        }



        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x312)	//WM_HOTKEY
            {

                Maximizer.ProcessHK(m.WParam, configuredMockScreens);


                return;
            }
            base.WndProc(ref m);
        }





        private void Form1_Load(object sender, EventArgs e)
        {
            Init();
            ComputeScreens();
        }


        private void textBoxMaxHK_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers != Keys.None)
                textBoxMaxHK.Text = e.Modifiers + " " + e.KeyCode;
            else
                textBoxMaxHK.Text = e.KeyCode.ToString();
            textBoxMaxHK.Tag = e;
        }

        private void textBoxResHK_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Modifiers != Keys.None)
                textBoxResHK.Text = e.Modifiers + " " + e.KeyCode;
            else
                textBoxResHK.Text = e.KeyCode.ToString();
            textBoxResHK.Tag = e;

        }

        private void buttonSave_Click(object sender, EventArgs e)
        {
            saveSettings();
            //Close();

        }

        private void saveSettings()
        {
            config.AppSettings.Settings.Clear();
            //config.AppSettings.Settings.Remove("maximize");
            KeyEventArgs max = (KeyEventArgs)textBoxMaxHK.Tag;
            max = new KeyEventArgs(Keys.F11 | Keys.Control | Keys.Shift); textBoxMaxHK.Text = "Shift, Control F11";
            

            if (max != null)
            {
                string maxS = "";
                maxS += max.Alt ? "1" : "0";
                maxS += max.Control ? "1" : "0";
                maxS += max.Shift ? "1" : "0";
                maxS += max.KeyValue;
                maxS += " " + textBoxMaxHK.Text;
                config.AppSettings.Settings.Add("maximize", maxS);
                maxKey = new Maximizer.ConfiguredKey(max.Alt, max.Control, max.Shift, max.KeyValue);
            }

            //config.AppSettings.Settings.Remove("restore");
            KeyEventArgs res = (KeyEventArgs)textBoxResHK.Tag;
            res = new KeyEventArgs(Keys.F9 | Keys.Control | Keys.Shift);textBoxResHK.Text="Shift, Control F9";
            
            
            if (res != null)
            {
                string resS = "";
                resS += res.Alt ? "1" : "0";
                resS += res.Control ? "1" : "0";
                resS += res.Shift ? "1" : "0";
                resS += res.KeyValue;
                resS += " " + textBoxResHK.Text;
                config.AppSettings.Settings.Add("restore", resS);
                resKey = new Maximizer.ConfiguredKey(res.Alt, res.Control, res.Shift, res.KeyValue);
            }



            //config.AppSettings.Settings.Remove("NumberOfConfiguredScreens");

            config.AppSettings.Settings.Add("NumberOfConfiguredScreens", configuredMockScreens.Count.ToString());
            int i = 0;
            foreach (KeyValuePair<string, MockScreen> kvp in configuredMockScreens)
            {
                MockScreen ms = kvp.Value;
                config.AppSettings.Settings.Add("ScreenDeviceName" + i, ms.DeviceName);
                config.AppSettings.Settings.Add("ScreenVertical" + i, ms.Vertical ? "true" : "false");
                config.AppSettings.Settings.Add("ScreenHorizontal" + i, ms.Horizontal ? "true" : "false");
                i++;
            }


            config.AppSettings.Settings.Add("UseWorkingArea", UseWorkingAreaCheckbox.Checked.ToString());
            config.Save(ConfigurationSaveMode.Minimal, true);
            Init();
            this.Hide();

        }


        private void configToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Show();
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.ExitThread();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            this.Hide();
        }



        public void Init()
        {
            Maximizer.RegisterHK(Handle, GetHashCode(), (Keys)maxKey.KeyCode,
                (maxKey.Alt ? Maximizer.MOD_ALT : 0) |
                (maxKey.Control ? Maximizer.MOD_CONTROL : 0) |
                (maxKey.Shift ? Maximizer.MOD_SHIFT : 0), "FullScreen");

            Maximizer.RegisterHK(Handle, GetHashCode(), (Keys)resKey.KeyCode,
                (resKey.Alt ? Maximizer.MOD_ALT : 0) |
                (resKey.Control ? Maximizer.MOD_CONTROL : 0) |
                (resKey.Shift ? Maximizer.MOD_SHIFT : 0), "RestoreOriginal");

        }














        private void ComputeScreens()
        {



            /*List<MockScreen> confScreens = new List<MockScreen>();
            confScreens.Add(new MockScreen(System.Windows.Forms.Screen.PrimaryScreen));
            confScreens.Add(new MockScreen(32, new Rectangle(-500, -100, 500, 400), "s0", false, new Rectangle(-500, -1050, 500, 400)));
            confScreens.Add(new MockScreen(32, new Rectangle(1280, 50, 500, 400), "s1", false, new Rectangle(-500, -1050, 500, 400)));

            /*			List<MockScreen> confScreens = new List<MockScreen>();
                        foreach (Screen cMockScreen in System.Windows.Forms.Screen.AllScreens)
                        {
                            confScreens.Add(new MockScreen(cMockScreen));
                        } */

            //			confScreens = null;

            /*	if (confScreens == null)
                {
                    confScreens = new Dictionary<string, MockScreen>();
                    confScreens.Add(System.Windows.Forms.Screen.PrimaryScreen.DeviceName, new MockScreen(System.Windows.Forms.Screen.PrimaryScreen));
                    confScreens.Add("s0", new MockScreen(32, new Rectangle(-500, -100, 500, 400), "s0", false, new Rectangle(-500, -1050, 500, 400)));
                    confScreens.Add("s1", new MockScreen(32, new Rectangle(1280, 50, 500, 400), "s1", false, new Rectangle(-500, -1050, 500, 400)));
                    confScreens.Add("s2", new MockScreen(32, new Rectangle(1980, 50, 500, 400), "s2", false, new Rectangle(-500, -1050, 500, 400)));

                }*/

            bool forceSet = (configuredMockScreens.Count == 0);
            foreach (Screen s in System.Windows.Forms.Screen.AllScreens)
            {


                string sDeviceName = Maximizer.neuterDeviceName(s.DeviceName);
                MockScreen ms = new MockScreen(s);
                if (configuredMockScreens.ContainsKey(Maximizer.neuterDeviceName(sDeviceName)))
                {

                    ms.Vertical = forceSet || configuredMockScreens[sDeviceName].Vertical;
                    ms.Horizontal = forceSet || configuredMockScreens[sDeviceName].Horizontal;
                    configuredMockScreens[sDeviceName] = ms;
                }
                else
                {
                    configuredMockScreens.Add(ms.DeviceName, ms);
                    configuredMockScreens[ms.DeviceName].Horizontal |= forceSet;
                    configuredMockScreens[ms.DeviceName].Vertical |= forceSet;
                }
            }


            List<string> mockScreensToRemove = new List<string>();
            foreach (KeyValuePair<string, MockScreen> kvp in configuredMockScreens)
            {
                if (kvp.Value.Incomplete)
                {
                    mockScreensToRemove.Add(kvp.Value.DeviceName);
                }
            }
            foreach (string s in mockScreensToRemove)
            {
                configuredMockScreens.Remove(s);
            }

            Rectangle wholeVirtualScreenBounds = Rectangle.Empty;
            foreach (KeyValuePair<string, MockScreen> s in configuredMockScreens)
            {
                wholeVirtualScreenBounds = Rectangle.Union(s.Value.Bounds, wholeVirtualScreenBounds);
            }


            int barWidth = Math.Max(5, Width / 30);
            int offset = 5;

            float fw = ((float)wholeVirtualScreenBounds.Width / (screensPanel.Width - 2 * offset));
            this.screensPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
            this.Height = screensPanel.Top + Height - screensPanel.Bottom + (int)((float)wholeVirtualScreenBounds.Height / fw) + 2 * offset + 2 * barWidth;
            screensPanel.Height = (int)((float)wholeVirtualScreenBounds.Height / fw) + 2 * offset + 2 * barWidth;
            this.screensPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));

            screensPanel.Controls.Clear();

            foreach (KeyValuePair<string, MockScreen> kvp in configuredMockScreens)
            {
                MockScreen cMockScreen = kvp.Value;
                Point controlPosition = new Point(
                    offset + (int)((float)cMockScreen.Bounds.Left / fw - (float)wholeVirtualScreenBounds.Left / fw),
                    offset + (int)((float)cMockScreen.Bounds.Top / fw - (float)wholeVirtualScreenBounds.Top / fw)
                    );


                Label screenLabel = new Label();
                screenLabel.TextAlign = ContentAlignment.MiddleCenter;
                screenLabel.BorderStyle = BorderStyle.FixedSingle;
                screenLabel.BackColor = SystemColors.ControlLightLight;
                screenLabel.AutoSize = false;
                screenLabel.Size = new SizeF(cMockScreen.Bounds.Width / fw, cMockScreen.Bounds.Height / fw).ToSize();
                screenLabel.Location = controlPosition;
                screenLabel.Text = cMockScreen.DeviceName + "\n" + cMockScreen.Bounds.Width + "x" + cMockScreen.Bounds.Height;
                screenLabel.Tag = cMockScreen;
                screenLabel.Name = "ScreenLabel";
                //toolTip1.SetToolTip(screenLabel, "Toggle the surrounding buttons to select the window span");



                CheckBox horizontalCheckbox = new CheckBox();
                horizontalCheckbox.Appearance = Appearance.Button;
                horizontalCheckbox.AutoSize = false;
                horizontalCheckbox.Size = new SizeF(cMockScreen.Bounds.Width / fw, barWidth).ToSize();
                horizontalCheckbox.Location = controlPosition;
                horizontalCheckbox.Checked = cMockScreen.Horizontal;
                horizontalCheckbox.Tag = cMockScreen;
                horizontalCheckbox.Name = "HorizontalCheckbox";
                //toolTip1.SetToolTip(horizontalCheckbox, "Toggle to span the window to this screen on width");

                CheckBox verticalCheckbox = new CheckBox();
                verticalCheckbox.Appearance = Appearance.Button;
                verticalCheckbox.AutoSize = false;
                verticalCheckbox.Size = new SizeF(barWidth, cMockScreen.Bounds.Height / fw).ToSize();
                verticalCheckbox.Location = controlPosition;
                verticalCheckbox.Checked = cMockScreen.Vertical;
                verticalCheckbox.Tag = cMockScreen;
                verticalCheckbox.Name = "VerticalCheckbox";
                //toolTip1.SetToolTip(verticalCheckbox, "Toggle to span the window to this screen on height");

                horizontalCheckbox.CheckedChanged += new EventHandler(horizontalCheckbox_CheckedChanged);
                verticalCheckbox.CheckedChanged += new EventHandler(verticalCheckbox_CheckedChanged);

                screensPanel.Controls.Add(verticalCheckbox);
                screensPanel.Controls.Add(horizontalCheckbox);
                screensPanel.Controls.Add(screenLabel);
            }
        }










        void verticalCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            ((MockScreen)(((CheckBox)sender).Tag)).Vertical = ((CheckBox)sender).Checked;
        }

        void horizontalCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            ((MockScreen)(((CheckBox)sender).Tag)).Horizontal = ((CheckBox)sender).Checked;
        }

        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            ComputeScreens();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            saveSettings();
            e.Cancel = true;
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            new AboutBox().ShowDialog(this);
        }

        private void Form1_HelpRequested(object sender, HelpEventArgs hlpevent)
        {

            Control helpControl = this.GetChildAtPoint(PointToClient(hlpevent.MousePos));

            if (helpControl == null)
            {
                Console.WriteLine("");
                ShowHelp(this);
                return;
            }
            if (helpControl == screensPanel)
            {
                helpControl = screensPanel.GetChildAtPoint(screensPanel.PointToClient(hlpevent.MousePos));
                if (helpControl == null)
                    return;
            }
            ShowHelp(helpControl);
        }


        private void ShowHelp(Control helpC)
        {
            if (mb == null)
                mb = new MessageBalloon(this);

            mb.Parent = helpC;
            mb.Align = BalloonAlignment.CenterMiddle;

            Console.WriteLine(helpC.Name);
            string helpText = global::VirtualScreenMaximizer.Properties.Resources.ResourceManager.GetString("help_" + helpC.Name);
            if (helpText == null)
                return;
            string[] helpTextSplit = helpText.Split(new char[1] { '|' }, 2);

            mb.TitleIcon = TooltipIcon.Info;
            mb.Title = helpTextSplit[0];
            mb.Text = helpTextSplit[1];

            mb.Show();
        }

        MessageBalloon mb = null;

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            if (Visible)
            {
                this.Hide();
            }
            else
            {
                this.Show();
            }


        }

        




 
    }


    public class ConfiguredMockScreens : Dictionary<string, MockScreen>
    {
        private bool useWorkingArea;
        public bool UseWorkingArea
        {
            get { return useWorkingArea; }
            set { useWorkingArea = value; }
        }



    }

}